package cn.kmsoft.stgeometry.landm;

import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.wololo.object.GeoJson;
import cn.kmsoft.wololo.object.GeoJsonFeature;
import cn.kmsoft.wololo.object.GeoJsonGeometry;
import com.alibaba.fastjson.JSONObject;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 土地land，其可以包括多个地块block
 *
 */
public class Land implements Serializable {
    //ring标识
    private static int oldRingFlag = 0;

    // 格式版本号
    private String formatVersion;
    // 数据产生单位
    private String dataProduceOrg;
    // 数据产生日期
    private String produceDate;

    // 坐标系
    private String coordinateSystem;
    // 几度分带
    private String degreeNo;
    // 投影类型
    private String projectionType;
    // 计量单位
    private String unit;
    // 带号
    private String degreeNum;
    // 精度
    private String precision;
    // 转换参数
    private String conversionParameter;
    // 地块集合
    private List<Block> blocks;

    public Land() {
        this.blocks = new ArrayList<Block>();
    }

    public Land(LandHeader header) {
        this.setFormatVersion(header.getFormatVersion());
        this.setDataProduceOrg(header.getDataProduceOrg());
        this.setProduceDate(header.getProduceDate());
        this.setCoordinateSystem(header.getCoordinateSystem());
        this.setDegreeNo(header.getDegreeNo());//几度分带
        this.setProjectionType(header.getProjectionType());
        this.setUnit(header.getUnit());
        this.setDegreeNum(header.getDegreeNum());
        this.setPrecision(header.getPrecision());//精度
        this.setConversionParameter(header.getConversionParameter());//精度

        this.blocks = new ArrayList<Block>();
    }

    // 属性集合
    public List<Block> getBlocks() {
        return blocks;
    }

    public String getFormatVersion() {
        return this.formatVersion;
    }

    public void setFormatVersion(String formatVersion) {
        this.formatVersion = formatVersion;
    }

    public String getDataProduceOrg() {
        return this.dataProduceOrg;
    }

    public void setDataProduceOrg(String dataProduceOrg) {
        this.dataProduceOrg = dataProduceOrg;
    }

    public String getProduceDate() {
        return this.produceDate;
    }

    public void setProduceDate(String produceDate) {
        this.produceDate = produceDate;
    }

    public String getCoordinateSystem() {
        return this.coordinateSystem;
    }

    public void setCoordinateSystem(String coordinateSystem) {
        this.coordinateSystem = coordinateSystem;
    }

    public String getDegreeNo() {
        return this.degreeNo;
    }

    public void setDegreeNo(String degreeNo) {
        this.degreeNo = degreeNo;
    }

    public String getProjectionType() {
        return this.projectionType;
    }

    public void setProjectionType(String projectionType) {
        this.projectionType = projectionType;
    }

    public String getUnit() {
        return this.unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    public String getDegreeNum() {
        return this.degreeNum;
    }

    public void setDegreeNum(String degreeNum) {
        this.degreeNum = degreeNum;
    }

    public String getPrecision() {
        return this.precision;
    }

    public void setPrecision(String precision) {
        this.precision = precision;
    }

    public String getConversionParameter() {
        return this.conversionParameter;
    }

    public void setConversionParameter(String conversionParameter) {
        this.conversionParameter = conversionParameter;
    }

    /**
     * 读取标准图形坐标串txt文件（清华三维导出，fme提取转换）
     *
     * @param filePath txt文件物理路径
     * @return
     */
    public static Land readTxtFile(String filePath) {
        oldRingFlag = 0;
        Land land = new Land();
        try {
            String encoding = "GBK";
            Block block = null;
            Ring ring = null;

            //读取txt文件
            File file = new File(filePath);
            if ((file.isFile()) && (file.exists())) {
                InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
                BufferedReader bufferedReader = new BufferedReader(read);

                //行数
                int lineNum = 0;
                //遍历每一行line，很重要
                String lineTxt = null;
                while ((lineTxt = bufferedReader.readLine()) != null) {
                    lineNum++;

                    //1、land txt 的基本信息（格式版本号=1.0版本）
                    if (lineTxt.indexOf("=") != -1) {
                        String[] line = lineTxt.split("=");

                        if ((line[0] != null) && (line[0].equals("格式版本号")) && line.length > 1) {
                            land.setFormatVersion(line[1]);
                        } else if ((line[0] != null) && (line[0].equals("数据产生单位")) && line.length > 1) {
                            land.setDataProduceOrg(line[1]);
                        } else if ((line[0] != null) && (line[0].equals("数据产生日期")) && line.length > 1) {
                            land.setProduceDate(line[1]);
                        } else if ((line[0] != null) && (line[0].equals("坐标系")) && line.length > 1) {
                            land.setCoordinateSystem(line[1]);
                        } else if ((line[0] != null) && (line[0].equals("几度分带")) && line.length > 1) {
                            land.setDegreeNo(line[1]);
                        } else if ((line[0] != null) && (line[0].equals("投影类型")) && line.length > 1) {
                            land.setProjectionType(line[1]);
                        } else if ((line[0] != null) && (line[0].equals("计量单位")) && line.length > 1) {
                            land.setUnit(line[1]);
                        } else if ((line[0] != null) && (line[0].equals("带号")) && line.length > 1) {
                            land.setDegreeNum(line[1]);
                        } else if ((line[0] != null) && (line[0].equals("精度")) && line.length > 1) {
                            land.setPrecision(line[1]);
                        } else if ((line[0] != null) && (line[0].equals("转换参数")) && line.length > 1) {
                            land.setConversionParameter(line[1]);
                        }
                    } else {
                        //2、新地块block 信息   1038,59.1068,13,13,面,,,地类编码,@
                        //通过@来分割
                        if (lineTxt.indexOf("@") != -1) {

                            //新建地块---同时新建地块环
                            block = new Block();
                            ring = new Ring();
                            oldRingFlag = 1;

                            //对每一行按照“，”号分割

                            String[] line = lineTxt.split(",");
                            if (!StringUtil.isNullOrEmpty(line[0])) {
                                int jzds = Integer.parseInt(line[0]);
                                block.getbAttrs().put("jzds", jzds);
                                block.setJzds(jzds);
                            }
                            if (!StringUtil.isNullOrEmpty(line[1])) {
                                Double dkmj = Double.parseDouble(line[1]);
                                block.getbAttrs().put("dkmj", dkmj);
                                block.setDkmj(dkmj);
                            }
                            if (!StringUtil.isNullOrEmpty(line[2])) {
                                String dkbh = line[2];
                                block.getbAttrs().put("dkbh", dkbh);
                                block.setDkbh(dkbh);
                            }
                            if (!StringUtil.isNullOrEmpty(line[3])) {
                                String dkmc = line[3];
                                block.getbAttrs().put("dkmc", dkmc);
                                block.setDkmc(dkmc);
                            }
                            if (!StringUtil.isNullOrEmpty(line[4])) {
                                String jltxsx = line[4];
                                block.getbAttrs().put("jltxsx", jltxsx);
                                block.setJltxsx(jltxsx);
                            }
                            if (!StringUtil.isNullOrEmpty(line[5])) {
                                String tfh = line[5];
                                block.getbAttrs().put("tfh", tfh);
                                block.setTfh(tfh);
                            }
                            if (!StringUtil.isNullOrEmpty(line[6])) {
                                String dkyt = line[6];
                                block.getbAttrs().put("dkyt", dkyt);
                                block.setDkyt(dkyt);
                            }

                            block.getRings().add(ring);
                            land.getBlocks().add(block);
                        } else {
                            //分割数据行的数据 J2,1,3297731.838,36371740.460
                            if (lineTxt.indexOf("J") != -1) {

                                String[] attrs = lineTxt.split(",");

                                //新环标识
                                int newringFlag = Integer.parseInt(attrs[1]);
                                if (newringFlag != oldRingFlag) {
                                    ring = new Ring();
                                    ring.setRingId(newringFlag);

                                    block.getRings().add(ring);
                                    //这个很关键
                                    oldRingFlag = newringFlag;
                                }

                                Point point = new Point();
                                //注意，txt中x为36-xxx，
                                if (!StringUtil.isNullOrEmpty(attrs[2])) {
                                    point.setY(Double.parseDouble(attrs[2]));
                                }
                                if (!StringUtil.isNullOrEmpty(attrs[3])) {
                                    String xstr = attrs[3];
                                    if (attrs[3].indexOf("|") != -1) {
                                        xstr = attrs[3].substring(0, attrs[3].indexOf("|"));
                                    }
                                    point.setX(Double.parseDouble(xstr));
                                }

                                ring.getPoints().add(point);
                            }
                        }
                    }
                }

                read.close();
            } else {
                System.out.println("找不到指定的文件");
            }
        } catch (Exception e) {
            System.out.println("读取文件内容出错");
            e.printStackTrace();
        }
        return land;
    }

    public String toTxtFile(String path, String txtName) {
        String txtFileName = path + "\\" + txtName;
        // 输出land中内容到txt文件中
        File outtxtfile = new File(txtFileName);

        try {
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(outtxtfile), "GBK"), true);

            //基本信息
            pw.println("[属性描述]");
            pw.println("格式版本号=" + this.getFormatVersion());
            pw.println("数据产生单位=" + this.getDataProduceOrg());
            pw.println("数据产生日期=" + this.getProduceDate());
            pw.println("坐标系=" + this.getCoordinateSystem());
            pw.println("几度分带=" + this.getDegreeNo());
            pw.println("投影类型=" + this.getProjectionType());
            pw.println("计量单位=" + this.getUnit());
            pw.println("带号=" + this.getDegreeNum());
            pw.println("精度=" + this.getPrecision());
            pw.println("转换参数=" + this.getConversionParameter());

            //坐标序列
            pw.println("[地块坐标]");

            int blockCount = this.getBlocks().size();
            for (int i = 0; i < blockCount; i++) {
                Block block = this.getBlocks().get(i);
                int ringCount = block.getRings().size();

                //获取某个地块block的界址点数
                int jzdCount = 0;
                for (int j = 0; j < ringCount; j++) {
                    Ring ring = block.getRings().get(j);
                    int ringJzdCount = ring.getPoints().size();

                    jzdCount += ringJzdCount;
                }

                int bhIndex = i + 1;
                String dkmj = String.format("%.4f", block.getDkmj());
                // String dkbh = block.getDkbh();
                String dkbh = "地块" + bhIndex;
                String dkmc = block.getDkmc();
                String jltxsx = block.getJltxsx();
                String tfh = block.getTfh();
                String dkyt = block.getDkyt();

                // 坐标序列台头
                // 界址点数,地块面积,地块编号,地块名称,记录图形属性(点、线、面),图幅号,地块用途,地类编码,@
                String blockHeader = String.format("%s,%s,%s,%s,%s,%s,%s,%s,%s", jzdCount, dkmj, dkbh,
                        dkmc, jltxsx, tfh, dkyt, "地类编码", "@");
                pw.println(blockHeader);

                for (int j = 0; j < ringCount; j++) {
                    Ring ring = block.getRings().get(j);
                    int pointCount = ring.getPoints().size();

                    int ringIndex = j + 1;
                    for (int k = 0; k < pointCount; k++) {
                        Point pt = ring.getPoints().get(k);
                        String y = String.format("%.3f", pt.getY());
                        String x = String.format("%.3f", pt.getX());

                        int jzdIndex = k + 1;
                        String jzdLabel = "J" + jzdIndex;
                        String jzdLine = String.format("%s,%s,%s,%s", jzdLabel, ringIndex, y, x);
                        //打印具体坐标点
                        pw.println(jzdLine);
                    }
                }
            }
            pw.flush();
            pw.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return txtFileName;
    }

    public String toJsonStr() {
        GeoJson geoJson = new GeoJson();
        try {
            List<GeoJsonFeature> features = new ArrayList<GeoJsonFeature>();
            //坐标序列
            int blockCount = this.getBlocks().size();
            for (int i = 0; i < blockCount; i++) {
                Block block = this.getBlocks().get(i);
                int ringCount = block.getRings().size();

                GeoJsonFeature fea = new GeoJsonFeature();

                //geo.setCoordinates(coordinates);
                //获取某个地块block的界址点数
                int jzdCount = 0;
                for (int ii = 0; ii < ringCount; ii++) {
                    Ring ring = block.getRings().get(ii);
                    int ringJzdCount = ring.getPoints().size();

                    jzdCount += ringJzdCount;
                }

                //属性信息
                Map<String, Object> properties = new HashMap<String, Object>();
                int bhIndex = i + 1;
                String dkmj = String.format("%.4f", block.getDkmj());
                // String dkbh = block.getDkbh();
                String dkbh = "地块" + bhIndex;
                String dkmc = block.getDkmc();
                String jltxsx = block.getJltxsx();
                String tfh = block.getTfh();
                String dkyt = block.getDkyt();
                properties.put("dkbh", dkbh);
                properties.put("dkmc", dkmc);
                properties.put("jltxsx", jltxsx);
                properties.put("tfh", tfh);
                properties.put("dkyt", dkyt);
                properties.put("dkmj", dkmj);

                fea.setType("feature");
                fea.setProperties(properties);

                //图形坐标串
                GeoJsonGeometry geo = new GeoJsonGeometry();
                geo.setType("Polygon");
                double[][][] coordinates = new double[ringCount][][];
                for (int j = 0; j < ringCount; j++) {
                    Ring ring = block.getRings().get(j);

                    int pointCount = ring.getPoints().size();
                    double[][] pointCoords = new double[pointCount][];
                    for (int k = 0; k < pointCount; k++) {
                        Point pt = ring.getPoints().get(k);
                        double x = Double.parseDouble(String.format("%.3f", pt.getX()));
                        double y = Double.parseDouble(String.format("%.3f", pt.getY()));

                        double[] coords = new double[2];
                        coords[0] = x;
                        coords[1] = y;

                        pointCoords[k] = coords;
                    }
                    coordinates[j] = pointCoords;
                }

                geo.setCoordinates(coordinates);
                fea.setGeometry(geo);
                features.add(fea);
            }

            geoJson.setFeatures(features);
            geoJson.setType("FeatureCollection");
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return JSONObject.toJSONString(geoJson);
    }

}
